package top.lingkang.finalgateway.monitor;

import lombok.extern.slf4j.Slf4j;
import org.noear.solon.Solon;
import top.lingkang.finalgateway.admin.entity.AccessLogEntity;
import top.lingkang.finalgateway.admin.mapper.AccessLogMapper;
import top.lingkang.finalgateway.admin.task.MonitorTask;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 监控流量归纳
 *
 * @author lingkang
 * Created by 2024/5/3
 */
@Slf4j
public class MonitorInduction {
    private final int port;
    private final AccessLogMapper accessLogMapper;
    private volatile int count = 0;

    public MonitorInduction(int port) {
        this.port = port;
        accessLogMapper = Solon.context().getBean(AccessLogMapper.class);
    }

    private final Lock lock = new ReentrantLock();
    private volatile List<AccessLogEntity> list = new ArrayList<>(700);

    public synchronized void add(String type, String ip, String method, String source, String target, long total) {
        AccessLogEntity access = new AccessLogEntity();
        Date date = new Date();
        // access.setId(IdUtils.id(date));
        access.setType(type);
        access.setSource(source);
        access.setTarget(target);
        access.setPort(port);
        access.setIp(ip);
        access.setMethod(method);
        access.setSize(total);
        access.setCreateTime(date);
        lock.lock();
        try {
            list.add(access);
            if (list.size() > 511) {
                refreshToFile();
                count++;
                if (count == 20) {// 1w请求触发一次检查
                    count = 0;
                    MonitorTask monitorTask = Solon.context().getBean(MonitorTask.class);
                    if ("tcp".equals(type))
                        monitorTask.accessMonitorHttp(new Date(System.currentTimeMillis() - 120000), port);
                    else
                        monitorTask.accessMonitorHttp(new Date(System.currentTimeMillis() - 120000), port);
                }
            }
        } catch (Exception e) {
            log.error("lock error", e);
        } finally {
            lock.unlock();
        }
    }

    public void refreshToFile() {
        if (list.isEmpty())
            return;
        accessLogMapper.insertBatch(list);
        list.clear();
    }

    public void accessWs(String ip, String source, String target, long len) {
        if (ip.startsWith("/"))
            ip = ip.substring(1);
        add("ws", ip, "GET", source, target, len);
    }

    public void accessTcp(String ip, Integer port, String host, Integer targetPort, long len) {
        add("tcp", ip, "TCP", ip + ":" + port, host + ":" + targetPort, len);
    }

}
